﻿using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Cms.Application.Admin.Views;
using Cms.Data;
using Cms.Domain;
using Cms.Domain.RepositoryInterfaces;

namespace Cms.Application.Admin.Presenters
{
    public class EditAdministratorPresenter : BasePresenter
    {
        private readonly Administrator _administrator;
        private readonly IEditAdministratorView _view;
        
        // Code-behind constructor
        public EditAdministratorPresenter(IEditAdministratorView view)
            : this(view, new RepositoryFactory())
        {
        }

        // Unit test constructor
        public EditAdministratorPresenter(IEditAdministratorView view, IRepositoryFactory repositoryFactory)
            : base(view, repositoryFactory)
        {
            _view = view;
            _administrator = AdministratorRepository.GetAdministrator(_view.AdministratorID);
            _view.HeadingText = GetText(_view, _view.EditedAdministratorID > 0 ? "EditHeading" : "NewHeading");
            if (!_administrator.HasPermission.EditAdministrator)
                _view.RedirectToPermissionDeniedPage();
        }

        public void Initialize()
        {
            IList<string> systemLocales = new List<string> { "en-US", "sv-SE" };
            _view.SetAdministratorGroups(AdministratorRepository.GetGroups());
            _view.SetAvailableSites(SiteRepository.GetSites());
            SetDefaultSites();
            _view.SetSystemLocales(systemLocales);
            if (_view.EditedAdministratorID == -1)
            {
                _view.SelectedAdministratorGroupID = 1;
                _view.SelectedDefaultSiteID = _administrator.CurrentSite.ID;
                _view.DefaultSystemLocale = _administrator.DefaultSystemLocale;
                DateTimeFormatInfo dtfi = new CultureInfo(_administrator.DefaultSystemLocale).DateTimeFormat;
                //_view.DateFormat = dtfi.ShortDatePattern;
                //_view.TimeFormat = dtfi.ShortTimePattern;
                _view.ShowIntroHelp = true;
            }
            else
            {
                Administrator admin = AdministratorRepository.GetAdministrator(_view.EditedAdministratorID);
                _view.Username = admin.Username;
                _view.Password = admin.Password;
                _view.Email = admin.Email;
                _view.Firstname = admin.Firstname;
                _view.Lastname = admin.Lastname;
                _view.DefaultSystemLocale = admin.DefaultSystemLocale;
                _view.SelectedAdministratorGroupID = admin.Group.ID;
                if (admin.DefaultSite != null)
                    _view.SelectedDefaultSiteID = admin.DefaultSite.ID;
                _view.DateFormat = admin.DateFormat;
                _view.TimeFormat = admin.TimeFormat;
                _view.FirstDayOfWeek = admin.FirstDayOfWeek;
                _view.ShowIntroHelp = admin.ShowIntroHelp;
            }
        }

        public void SetDefaultSites()
        {
            IEnumerable<int> availableSiteIDs = _view.GetSelectedAvailableSiteIDs();
            IList<Site> sites = availableSiteIDs.Select(id => SiteRepository.GetSite(id)).ToList();
            _view.SetDefaultSites(sites);
        }
        
        public bool HasAccessTo(Site site)
        {
            Administrator admin = AdministratorRepository.GetAdministrator(_view.EditedAdministratorID);
            return _view.SelectedAdministratorGroupID == 1 || site.Administrators.FirstOrDefault(a => admin != null && a.ID == admin.ID) != null;
        }

        public void Save()
        {
            if (_view.Username.Trim() == string.Empty)
                AddValidationError(1, GetText(_view, "NoUsernameError"));
            else if (AdministratorRepository.UsernameExists(_view.Username, _view.EditedAdministratorID))
                AddValidationError(2, GetText(_view, "UsernameExistsError"));
            if (_view.Password == null || _view.Password.Trim() == string.Empty)
                AddValidationError(3, GetText(_view, "NoPasswordError"));
            if (!IsValid)
                return;
            Administrator admin = _view.EditedAdministratorID == -1
                                      ? new Administrator()
                                      : AdministratorRepository.GetAdministrator(_view.EditedAdministratorID);
            admin.DefaultSite = SiteRepository.GetSite(_view.SelectedDefaultSiteID);
            admin.DefaultSystemLocale = _view.DefaultSystemLocale;
            admin.Email = _view.Email;
            admin.Firstname = _view.Firstname;
            admin.Lastname = _view.Lastname;
            admin.Password = _view.Password;
            admin.Username = _view.Username;
            admin.Group = AdministratorRepository.GetGroup(_view.SelectedAdministratorGroupID);
            if (_view.EditedAdministratorID == -1)
            {
                admin.CurrentSite = admin.DefaultSite;
                admin.CurrentSiteLocale = admin.DefaultSite.DefaultLocale;
            }
            admin.DateFormat = _view.DateFormat;
            admin.TimeFormat = _view.TimeFormat;
            admin.FirstDayOfWeek = _view.FirstDayOfWeek;
            admin.ShowIntroHelp = _view.ShowIntroHelp;
            int siteCountBefore = admin.AvailableSites.Count;
            foreach (Site site in admin.AvailableSites)
                site.Administrators.Remove(admin);
            admin.AvailableSites.Clear();
            if (admin.Group.ID == 1) 
            {
                // Administrator group, add all sites in the system
                foreach (Site site in SiteRepository.GetSites())
                {
                    site.Administrators.Add(admin);
                    admin.AvailableSites.Add(site);
                }
            }
            else
            {
                foreach (Site site in _view.GetSelectedAvailableSiteIDs().Select(id => SiteRepository.GetSite(id)))
                {
                    site.Administrators.Add(admin);
                    admin.AvailableSites.Add(site);
                }
            }
            if (admin.AvailableSites.Count < siteCountBefore)
                admin.ForceLogout = true;
            AdministratorRepository.SaveAdministrator(admin);
            _view.SetEditedAdministratorID(admin.ID);
        }
    }
}